package com.yy.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;

import java.util.Map;

/**
 * 应用程序上下文跑龙套
 * 描述：应用程序上下文工具类,通过此类可以获取当前环境下的spring容器； 容器的加载只在程序启动时初始化一次
 *
 * @author zhiqiang.sun
 * @date 2022/06/22
 */
public final class ApplicationContextUtil {
    private static ApplicationContext context = null;

    private ApplicationContextUtil() {
    }

    public static void initialize(ApplicationContext sc) {
        ApplicationContextUtil.context = sc;
    }

    /**
     * 描述：获取spring容器
     *
     * @return 返回spring容器applicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return context;
    }

    /**
     * 描述：根据实例类型获取spring容器的配置的实例对象
     *
     * @param clazz 实例的类型
     * @return 返回具体的实例对象
     * @throws BeansException - 如果bean不存在
     */
    public static <T> T loadBean(Class<T> clazz) throws BeansException {
        return context.getBean(clazz);
    }

    /**
     * 描述：根据实例类型获取spring容器的配置的实例对象
     *
     * @param clazz 实例的类型
     * @return 返回具体的实例对象
     * @throws BeansException - 如果bean不存在
     */
    public static <T> Map<String, T> loadBeans(Class<T> clazz) throws BeansException {
        return context.getBeansOfType(clazz);
    }

    /**
     * 描述:根据类名称获取spring容器中的实例对象
     *
     * @param beanName 实例名称
     * @return 返回实例对象
     * @throws BeansException - 如果bean不存在
     */
    @SuppressWarnings("unchecked")
    public static <T> T loadBean(String beanName) throws BeansException {
        return (T) context.getBean(beanName);
    }

    /**
     * 描述：根据实例类型获取spring容器的配置的实例对象
     *
     * @param clazz 实例的类型
     * @return 返回具体的实例对象，如果发生异常返回null
     */
    public static <T> T getBean(Class<T> clazz) {
        try {
            return context.getBean(clazz);
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 描述：根据实例类型获取spring容器的配置的实例对象
     *
     * @param clazz 实例的类型
     * @return 返回具体的实例对象，如果不存在指定类型bean，返回null
     */
    public static <T> Map<String, T> getBeans(Class<T> clazz) throws BeansException {
        try {
            return context.getBeansOfType(clazz);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 描述:根据类名称获取spring容器中的实例对象
     *
     * @param beanName 实例名称
     * @return 返回实例对象，如果发生异常返回null
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String beanName) {
        try {
            return (T) context.getBean(beanName);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 描述:根据类名称获取spring容器中的实例对象
     *
     * @param beanName 实例名称
     * @return 返回实例对象，如果发生异常返回null
     */
    public static <T> T getBean(String beanName, Class<T> clz) {
        try {
            return (T) context.getBean(beanName, clz);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的对象定义，则返回true，否则返回false
     *
     * @param name 对象注册名
     * @return boolean 包含则返回true，否则返回false
     */
    public static boolean containsBean(String name) {
        return context.containsBean(name);
    }

    /**
     * 判断以给定名字注册的对象定义是一个singleton还是一个prototype。 如果与给定名字相应的对象定义没有被找到，返回false
     *
     * @param name 对象注册名
     * @return boolean 单例返回true，否则返回false
     */
    public static boolean isSingleton(String name) {
        try {
            return context.isSingleton(name);
        } catch (NoSuchBeanDefinitionException e) {
            return false;
        }
    }

    /**
     * 获得给定名字注册的对象 class类型
     *
     * @param name 对象注册名
     * @return Class 注册对象的类型
     * @throws NoSuchBeanDefinitionException - 如果bean不存在
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return context.getType(name);
    }

    /**
     * 如果给定的对象名字在对象定义中有别名，则返回这些别名
     *
     * @param name 对象注册名
     * @return 对象别名
     * @throws NoSuchBeanDefinitionException - 如果bean不存在
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return context.getAliases(name);
    }

}
